use crate::error::{Result, PipitError};
use crate::vm::Value;
use std::collections::{VecDeque, BinaryHeap};
use std::sync::atomic::{AtomicBool, Ordering};
use std::cmp::Ordering as CmpOrdering;
use std::time::Instant;

// 惰性数据内存池 - 只用于存储惰性数据，不涉及GC
#[derive(Debug)]
pub struct LazyMemoryPool {
    // 不同类型惰性数据的存储池
    integer_pool: VecDeque<LazyData<i32>>,
    boolean_pool: VecDeque<LazyData<bool>>,
    float_pool: VecDeque<LazyData<f64>>,
    string_pool: VecDeque<LazyData<String>>,
    
    // 栈数据 - 使用BinaryHeap实现按时间戳排序
    stack_data: BinaryHeap<StackItem>,
    
    // 池容量限制
    capacity: usize,
    
    // 统计信息
    stats: PoolStats,
    
    // 批处理相关配置
    batch_size: usize,
    max_stack_size: usize,
    cleanup_in_progress: AtomicBool,
}

// 惰性数据包装器
#[derive(Debug)]
pub struct LazyData<T> {
    pub data: T,
    pub last_accessed: u64, // 最后访问时间戳
    pub access_count: u32,  // 访问次数
}

// 数据类型枚举
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataType {
    Integer,
    Boolean,
    Float,
    String,
}

// 栈数据项 - 用于按时间戳排序
#[derive(Debug)]
pub enum StackItem {
    Integer(i32, u64),      // 值, 时间戳
    Boolean(bool, u64),
    Float(f64, u64),
    String(String, u64),
}

// 内存池操作枚举
#[derive(Debug)]
pub enum PoolOperation {
    AllocateInteger(i32),
    AllocateBoolean(bool),
    AllocateFloat(f64),
    AllocateString(String),
    Reclaim(f64), // 回收指定百分比的对象
}

// 内存池操作结果枚举
#[derive(Debug)]
pub enum PoolResult {
    Integer(Value),
    Boolean(Value),
    Float(Value),
    String(Value),
    Reclaimed(usize), // 回收的对象数量
}

// 为了在BinaryHeap中按时间戳排序，我们需要实现PartialOrd和Ord
impl PartialEq for StackItem {
    fn eq(&self, other: &Self) -> bool {
        self.get_timestamp() == other.get_timestamp()
    }
}

impl Eq for StackItem {}

impl PartialOrd for StackItem {
    fn partial_cmp(&self, other: &Self) -> Option<CmpOrdering> {
        // BinaryHeap默认是最大堆，这里我们反转顺序使其成为最小堆（按时间戳升序）
        other.get_timestamp().partial_cmp(&self.get_timestamp())
    }
}

impl Ord for StackItem {
    fn cmp(&self, other: &Self) -> CmpOrdering {
        self.partial_cmp(other).unwrap_or(CmpOrdering::Equal)
    }
}

impl StackItem {
    // 获取时间戳
    fn get_timestamp(&self) -> u64 {
        match self {
            StackItem::Integer(_, ts) => *ts,
            StackItem::Boolean(_, ts) => *ts,
            StackItem::Float(_, ts) => *ts,
            StackItem::String(_, ts) => *ts,
        }
    }
    
    // 获取数据类型
    fn data_type(&self) -> DataType {
        match self {
            StackItem::Integer(_, _) => DataType::Integer,
            StackItem::Boolean(_, _) => DataType::Boolean,
            StackItem::Float(_, _) => DataType::Float,
            StackItem::String(_, _) => DataType::String,
        }
    }
    
    // 获取整数值（如果适用）
    fn value(&self) -> i64 {
        match self {
            StackItem::Integer(val, _) => *val as i64,
            StackItem::Boolean(val, _) => if *val { 1 } else { 0 },
            StackItem::Float(val, _) => *val as i64, // 近似值
            StackItem::String(_, _) => 0, // 字符串无法直接转为整数
        }
    }
}

// 池统计信息
#[derive(Debug, Default)]
pub struct PoolStats {
    pub allocations: u64,
    pub deallocations: u64,
    pub pool_hits: u64,
    pub pool_misses: u64,
    pub bytes_saved: u64,
}

impl LazyMemoryPool {
    pub fn new(capacity: usize) -> Self {
        LazyMemoryPool {
            integer_pool: VecDeque::with_capacity(capacity / 4),
            boolean_pool: VecDeque::with_capacity(capacity / 8),
            float_pool: VecDeque::with_capacity(capacity / 4),
            string_pool: VecDeque::with_capacity(capacity / 2),
            stack_data: BinaryHeap::new(),
            capacity,
            stats: PoolStats::default(),
            batch_size: 100,  // 一次处理的批量大小
            max_stack_size: 10000,  // 栈的最大大小
            cleanup_in_progress: AtomicBool::new(false),
        }
    }
    
    // 获取当前时间戳（用于LRU算法）
    fn current_timestamp(&self) -> u64 {
        // 简化实现，实际应用中应该使用高精度计时器
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .map(|d| d.as_millis() as u64)
            .unwrap_or(0)
    }
    
    // 将数据添加到栈
    pub fn push_to_stack(&mut self, item: StackItem) -> Result<()> {
        // 检查栈是否已满
        if self.stack_data.len() >= self.max_stack_size {
            // 当栈达到阈值时，自动触发清理
            self.cleanup_stack_if_needed(true)?;
        }
        
        // 添加到栈
        self.stack_data.push(item);
        self.stats.allocations += 1;
        
        // 检查是否需要触发清理
        self.cleanup_stack_if_needed(false)?;
        
        Ok(())
    }
    
    // 检查是否需要清理栈并执行清理
    pub fn cleanup_stack_if_needed(&mut self, force: bool) -> Result<()> {
        // 防止并发清理
        if self.cleanup_in_progress.load(Ordering::SeqCst) {
            return Ok(());
        }
        
        // 判断是否需要清理
        let should_cleanup = force || 
                           self.stack_data.len() > (self.max_stack_size * 80 / 100);
        
        if !should_cleanup {
            return Ok(());
        }
        
        // 标记清理中
        if !self.cleanup_in_progress.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_ok() {
            return Ok(());
        }
        
        let result = self.batch_process_stack();
        
        // 清理完成
        self.cleanup_in_progress.store(false, Ordering::SeqCst);
        
        result
    }
    
    // 批量处理栈中的数据，将其复制到对应的内存池
    fn batch_process_stack(&mut self) -> Result<()> {
        let mut processed_count = 0;
        
        // 创建一个临时向量来存储要处理的项目，避免在循环中修改heap
        let mut items_to_process = Vec::new();
        
        // 取出最多batch_size个项目
        while let Some(item) = self.stack_data.pop() {
            items_to_process.push(item);
            if items_to_process.len() >= self.batch_size {
                break;
            }
        }
        
        // 按时间戳排序（从最旧到最新）
        items_to_process.sort_by(|a, b| a.get_timestamp().cmp(&b.get_timestamp()));
        
        // 处理每个项目
        for item in items_to_process {
            match item {
                StackItem::Integer(value, _timestamp) => {
                    self.store_integer(value)?;
                    processed_count += 1;
                },
                StackItem::Boolean(value, _timestamp) => {
                    self.store_boolean(value)?;
                    processed_count += 1;
                },
                StackItem::Float(value, _timestamp) => {
                    self.store_float(value)?;
                    processed_count += 1;
                },
                StackItem::String(value, _timestamp) => {
                    self.store_string(value)?;
                    processed_count += 1;
                },
            }
        }
        
        // 更新统计信息
        self.stats.deallocations += processed_count as u64;
        
        Ok(())
    }
    
    // 获取栈当前大小
    pub fn stack_size(&self) -> usize {
        self.stack_data.len()
    }
    
    // 从池中获取或创建一个整数值（惰性数据）
    pub fn get_integer(&mut self, value: i32) -> Result<Value> {
        self.stats.allocations += 1;
        
        // 扩展缓存范围：常用整数、2的幂次、斐波那契数列等
        let should_cache = self.should_cache_integer(value);
        
        if should_cache {
            // 使用HashMap提高查找效率
            let key = value;
            if let Some(index) = self.integer_pool.iter().position(|item| item.data == key) {
                // 找到匹配项，更新访问信息
                let mut lazy_data = self.integer_pool.remove(index).unwrap();
                lazy_data.last_accessed = self.current_timestamp();
                lazy_data.access_count += 1;
                
                // 自适应调整：高频访问项移到队尾，低频项前移
                if lazy_data.access_count > 10 {
                    self.integer_pool.push_back(lazy_data);
                } else {
                    self.integer_pool.push_front(lazy_data);
                }
                
                self.stats.pool_hits += 1;
                self.stats.bytes_saved += std::mem::size_of::<i32>() as u64;
                
                return Ok(Value::Integer(value));
            }
            
            self.stats.pool_misses += 1;
            
            // 自动学习：将新遇到的常用值加入缓存
            if self.should_auto_cache_integer(value) {
                self.store_integer(value)?;
            }
        }
        
        Ok(Value::Integer(value))
    }
    
    // 将整数值作为惰性数据存储到池中
    pub fn store_integer(&mut self, value: i32) -> Result<()> {
        // 只存储常用整数值作为惰性数据
        if (value >= -10 && value <= 10) || value == 100 || value == 1000 {
            // 检查是否已存在
            if !self.integer_pool.iter().any(|item| item.data == value) {
                // 如果池已满，移除最少使用的项（队首）
                if self.integer_pool.len() >= self.capacity / 4 {
                    match self.integer_pool.pop_front() {
                        Some(_) => self.stats.deallocations += 1,
                        None => return Err(PipitError::RuntimeError("Failed to deallocate integer from pool".to_string()))
                    };
                }
                
                // 存储新的惰性数据
                self.integer_pool.push_back(LazyData {
                    data: value,
                    last_accessed: self.current_timestamp(),
                    access_count: 0,
                });
            }
        }
        
        Ok(())
    }
    
    // 从池中获取或创建一个布尔值（惰性数据）
    pub fn get_boolean(&mut self, value: bool) -> Result<Value> {
        self.stats.allocations += 1;
        
        // 查找匹配的值
        if let Some(index) = self.boolean_pool.iter().position(|item| item.data == value) {
            // 找到匹配项，更新访问信息
            let mut lazy_data = match self.boolean_pool.remove(index) {
                Some(data) => data,
                None => return Err(PipitError::RuntimeError("Failed to retrieve boolean from pool".to_string()))
            };
            lazy_data.last_accessed = self.current_timestamp();
            lazy_data.access_count += 1;
            
            // 将访问过的数据移到队尾（LRU策略）
            self.boolean_pool.push_back(lazy_data);
            
            self.stats.pool_hits += 1;
            self.stats.bytes_saved += std::mem::size_of::<bool>() as u64;
            
            return Ok(Value::Boolean(value));
        }
        
        self.stats.pool_misses += 1;
        Ok(Value::Boolean(value))
    }
    
    // 将布尔值作为惰性数据存储到池中
    pub fn store_boolean(&mut self, value: bool) -> Result<()> {
        // 检查是否已存在
        if !self.boolean_pool.iter().any(|item| item.data == value) {
            // 如果池已满，移除最少使用的项（队首）
            if self.boolean_pool.len() >= self.capacity / 8 {
                match self.boolean_pool.pop_front() {
                    Some(_) => self.stats.deallocations += 1,
                    None => return Err(PipitError::RuntimeError("Failed to deallocate boolean from pool".to_string()))
                };
            }
            
            // 存储新的惰性数据
            self.boolean_pool.push_back(LazyData {
                data: value,
                last_accessed: self.current_timestamp(),
                access_count: 0,
            });
        }
        
        Ok(())
    }
    
    // 从池中获取或创建一个浮点值（惰性数据）
    pub fn get_float(&mut self, value: f64) -> Result<Value> {
        self.stats.allocations += 1;
        
        // 对于常用浮点值，检查池中是否有匹配的惰性数据
        if is_common_float(value) {
            // 查找匹配的值
            if let Some(index) = self.float_pool.iter().position(|item| 
                (item.data - value).abs() < std::f64::EPSILON
            ) {
                // 找到匹配项，更新访问信息
                let mut lazy_data = match self.float_pool.remove(index) {
                    Some(data) => data,
                    None => return Err(PipitError::RuntimeError("Failed to retrieve float from pool".to_string()))
                };
                lazy_data.last_accessed = self.current_timestamp();
                lazy_data.access_count += 1;
                
                // 将访问过的数据移到队尾（LRU策略）
                self.float_pool.push_back(lazy_data);
                
                self.stats.pool_hits += 1;
                self.stats.bytes_saved += std::mem::size_of::<f64>() as u64;
                
                return Ok(Value::Float(value));
            }
            
            self.stats.pool_misses += 1;
        }
        
        Ok(Value::Float(value))
    }
    
    // 将浮点值作为惰性数据存储到池中
    pub fn store_float(&mut self, value: f64) -> Result<()> {
        // 只存储常用浮点值作为惰性数据
        if is_common_float(value) {
            // 检查是否已存在
            if !self.float_pool.iter().any(|item| 
                (item.data - value).abs() < std::f64::EPSILON
            ) {
                // 如果池已满，移除最少使用的项（队首）
                if self.float_pool.len() >= self.capacity / 4 {
                    match self.float_pool.pop_front() {
                        Some(_) => self.stats.deallocations += 1,
                        None => return Err(PipitError::RuntimeError("Failed to deallocate float from pool".to_string()))
                    };
                }
                
                // 存储新的惰性数据
                self.float_pool.push_back(LazyData {
                    data: value,
                    last_accessed: self.current_timestamp(),
                    access_count: 0,
                });
            }
        }
        
        Ok(())
    }
    
    // 从池中获取或创建一个字符串（惰性数据）
    pub fn get_string(&mut self, value: &str) -> Result<Value> {
        self.stats.allocations += 1;
        
        // 对于常用字符串，检查池中是否有匹配的惰性数据
        if is_common_string(value) {
            // 查找匹配的值
            if let Some(index) = self.string_pool.iter().position(|item| item.data == value) {
                // 找到匹配项，更新访问信息
                let mut lazy_data = match self.string_pool.remove(index) {
                    Some(data) => data,
                    None => return Err(PipitError::RuntimeError("Failed to retrieve string from pool".to_string()))
                };
                let data_clone = lazy_data.data.clone(); // 先克隆数据，避免moved value问题
                lazy_data.last_accessed = self.current_timestamp();
                lazy_data.access_count += 1;
                
                // 将访问过的数据移到队尾（LRU策略）
                self.string_pool.push_back(lazy_data);
                
                self.stats.pool_hits += 1;
                self.stats.bytes_saved += (value.len() + std::mem::size_of::<String>()) as u64;
                
                return Ok(Value::String(data_clone));
            }
            
            self.stats.pool_misses += 1;
        }
        
        // 直接创建字符串值
        let string_value = String::from(value);
        Ok(Value::String(string_value))
    }
    
    // 将字符串作为惰性数据存储到池中
    pub fn store_string(&mut self, value: String) -> Result<()> {
        // 只存储常用字符串作为惰性数据
        if is_common_string(&value) {
            // 检查是否已存在
            if !self.string_pool.iter().any(|item| item.data == value) {
                // 如果池已满，移除最少使用的项（队首）
                if self.string_pool.len() >= self.capacity / 2 {
                    match self.string_pool.pop_front() {
                        Some(_) => self.stats.deallocations += 1,
                        None => return Err(PipitError::RuntimeError("Failed to deallocate string from pool".to_string()))
                    };
                }
                
                // 存储新的惰性数据
                self.string_pool.push_back(LazyData {
                    data: value,
                    last_accessed: self.current_timestamp(),
                    access_count: 0,
                });
            }
        }
        
        Ok(())
    }
    
    // 智能判断是否应该缓存整数
    fn should_cache_integer(&self, value: i32) -> bool {
        // 1. 常用范围
        if (-100..=100).contains(&value) { return true; }
        
        // 2. 2的幂次
        if value > 0 && (value & (value - 1)) == 0 { return true; }
        
        // 3. 斐波那契数列相关
        let fib_numbers = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987];
        if fib_numbers.contains(&value.abs()) { return true; }
        
        // 4. 10的倍数
        if value % 10 == 0 && value.abs() <= 1000 { return true; }
        
        false
    }
    
    // 自动学习：判断是否应该将新值加入缓存
    fn should_auto_cache_integer(&self, value: i32) -> bool {
        // 基于访问模式和值频率的智能判断
        let total_accesses = self.stats.allocations;
        
        // 常见整数值范围
        let common_range = (-10000..=10000).contains(&value);
        
        // 特殊常用值检查
        let special_value = value == 0 || value == 1 || value == -1 || 
                          value == 100 || value == -100 || value == 1000 || value == -1000;
        
        // 2的幂次值
        let power_of_two = value > 0 && (value & (value - 1)) == 0;
        
        // 访问频率高且值在合理范围，或为特殊常用值时自动缓存
        if special_value || power_of_two {
            return true; // 特殊值和2的幂次总是缓存
        }
        
        if total_accesses > 1000 && common_range {
            return true; // 高访问量且在合理范围内
        }
        
        false
    }
    
    // 回收池中的对象
    pub fn reclaim_objects(&mut self, target_percentage: f64) -> usize {
        if self.cleanup_in_progress.load(Ordering::SeqCst) {
            return 0; // 清理已经在进行中
        }
        
        self.cleanup_in_progress.store(true, Ordering::SeqCst);
        let mut reclaimed_count = 0;
        
        // 计算需要回收的对象数量
        let total_objects = self.integer_pool.len() + self.boolean_pool.len() + 
                          self.float_pool.len() + self.string_pool.len();
        let target_reclaim = (total_objects as f64 * target_percentage) as usize;
        
        // 优先回收较长时间未使用的对象
        if !self.stack_data.is_empty() {
            // 回收栈数据中最老的对象
            let mut temp_stack = Vec::new();
            
            while let Some(item) = self.stack_data.pop() {
                // 尝试回收对象
                match &item {
                    StackItem::Integer(value, _) => {
                        if let Some(pos) = self.integer_pool.iter().position(
                            |x| x.data == *value
                        ) {
                            self.integer_pool.remove(pos);
                            reclaimed_count += 1;
                        }
                    },
                    StackItem::Boolean(value, _) => {
                        if let Some(pos) = self.boolean_pool.iter().position(
                            |x| x.data == *value
                        ) {
                            self.boolean_pool.remove(pos);
                            reclaimed_count += 1;
                        }
                    },
                    StackItem::Float(value, _) => {
                        if let Some(pos) = self.float_pool.iter().position(
                            |x| (x.data - *value).abs() < std::f64::EPSILON
                        ) {
                            self.float_pool.remove(pos);
                            reclaimed_count += 1;
                        }
                    },
                    StackItem::String(value, _) => {
                        if let Some(pos) = self.string_pool.iter().position(
                            |x| x.data == *value
                        ) {
                            self.string_pool.remove(pos);
                            reclaimed_count += 1;
                        }
                    },
                }
                
                // 如果已达到目标回收数量，停止回收
                if reclaimed_count >= target_reclaim {
                    // 将剩余的项放回堆中
                    temp_stack.push(item);
                    break;
                }
                
                // 保留最近的20%对象
                if reclaimed_count > (total_objects * 80) / 100 {
                    temp_stack.push(item);
                }
            }
            
            // 恢复剩余的项到堆中
            for item in temp_stack {
                self.stack_data.push(item);
            }
        }
        
        // 更新统计信息
        self.stats.deallocations += reclaimed_count as u64;
        self.cleanup_in_progress.store(false, Ordering::SeqCst);
        
        reclaimed_count
    }
    
    // 批量处理对象请求，提高性能
    pub fn batch_process(&mut self, batch: Vec<PoolOperation>) -> Result<Vec<PoolResult>> {
        let mut results = Vec::with_capacity(batch.len());
        
        // 统计批处理前的状态
        let start_time = Instant::now();
        
        for op in batch {
            match op {
                PoolOperation::AllocateInteger(value) => {
                    match self.get_integer(value) {
                        Ok(val) => {
                            results.push(PoolResult::Integer(val));
                        },
                        Err(e) => return Err(e),
                    }
                },
                PoolOperation::AllocateBoolean(value) => {
                    match self.get_boolean(value) {
                        Ok(val) => {
                            results.push(PoolResult::Boolean(val));
                        },
                        Err(e) => return Err(e),
                    }
                },
                PoolOperation::AllocateFloat(value) => {
                    match self.get_float(value) {
                        Ok(val) => {
                            results.push(PoolResult::Float(val));
                        },
                        Err(e) => return Err(e),
                    }
                },
                PoolOperation::AllocateString(value) => {
                    // 对短字符串进行特殊处理
                    if value.len() <= 32 {
                        match self.get_string(&value) {
                            Ok(val) => {
                                results.push(PoolResult::String(val));
                            },
                            Err(e) => return Err(e),
                        }
                    } else {
                        // 长字符串直接分配，不放入池
                        results.push(PoolResult::String(Value::String(value)));
                        self.stats.allocations += 1;
                        self.stats.pool_misses += 1; // 统计为未命中
                    }
                },
                PoolOperation::Reclaim(target_percentage) => {
                    let reclaimed = self.reclaim_objects(target_percentage);
                    results.push(PoolResult::Reclaimed(reclaimed));
                },
            }
        }
        
        // 记录批处理性能
        let _elapsed = start_time.elapsed();
        
        Ok(results)
    }

    // 获取统计信息
    pub fn get_stats(&self) -> &PoolStats {
        &self.stats
    }

    // 获取当前命中率
    pub fn get_hit_rate(&self) -> f64 {
        let total = self.stats.pool_hits + self.stats.pool_misses;
        if total == 0 { 0.0 } else {
            self.stats.pool_hits as f64 / total as f64
        }
    }

    // 清空内存池
    pub fn clear(&mut self) {
        self.integer_pool.clear();
        self.boolean_pool.clear();
        self.float_pool.clear();
        self.string_pool.clear();
    }
    
    // 清理不常用的惰性数据
    pub fn cleanup_unused(&mut self, threshold: u32) -> Result<()> {
        let current_time = self.current_timestamp();
        
        // 清理整数池
        self.integer_pool.retain(|item| {
            item.access_count >= threshold || 
            (current_time - item.last_accessed) < 60000 // 1分钟内访问过的保留
        });
        
        // 清理布尔池
        self.boolean_pool.retain(|item| {
            item.access_count >= threshold || 
            (current_time - item.last_accessed) < 60000
        });
        
        // 清理浮点池
        self.float_pool.retain(|item| {
            item.access_count >= threshold || 
            (current_time - item.last_accessed) < 60000
        });
        
        // 清理字符串池
        self.string_pool.retain(|item| {
            item.access_count >= threshold || 
            (current_time - item.last_accessed) < 60000
        });
        
        Ok(())
    }
}

// 检查是否为常用浮点值
fn is_common_float(value: f64) -> bool {
    // 常用的浮点值：0.0, 1.0, 0.5, 2.0等
    let common_floats = [0.0, 1.0, 2.0, 0.5, -1.0, 10.0, 100.0, 0.1, 0.25, 2.5];
    common_floats.iter().any(|&f| (f - value).abs() < std::f64::EPSILON)
}

// 检查是否为常用字符串
fn is_common_string(value: &str) -> bool {
    // 常用的字符串：空字符串、常见的关键字等
    let common_strings = ["", "true", "false", "null", "undefined", "ok", "error", "success", "fail"];
    common_strings.contains(&value)
}

// 通用的内存预分配工具
pub fn preallocate_with_capacity<T>(expected_size: usize) -> Vec<T> {
    Vec::with_capacity(expected_size)
}

// 内存使用优化工具
pub fn optimize_memory_usage<T>(collection: &mut Vec<T>, shrink_threshold: f64) {
    // 当集合容量远大于元素数量时收缩容量
    let capacity = collection.capacity();
    let len = collection.len();
    
    if capacity > 0 && (len as f64 / capacity as f64) < shrink_threshold {
        collection.shrink_to_fit();
    }
}